package net.pws.oos.biz.service.export;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import net.pws.common.event.ApplicationEventBus;
import net.pws.common.event.ApplicationEventObject;
import net.pws.common.util.DateUtils;
import net.pws.common.util.IoUtil;
import net.pws.common.util.NumberUtils;
import net.pws.common.simplemq.Action;
import net.pws.common.simplemq.Context;
import net.pws.oos.biz.BizException;
import net.pws.oos.biz.event.TaskExcelExportFailedEventObject;
import net.pws.oos.biz.event.TaskExcelExportSucceedEventObject;
import net.pws.oos.biz.model.Attachment;
import net.pws.oos.biz.query.AttachmentFinder;
import net.pws.oos.biz.query.TaskFinder;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("taskExcelExporter")
@SuppressWarnings("rawtypes")
public class TaskExcelExporter implements Action {
    
    private static final Log logger = LogFactory.getLog(TaskExcelExporter.class);
    
    private static final int MAX_WORD_IMAGE = 8;
    
    @Autowired
    private TaskFinder taskFinder;
    
    @Autowired
    private AttachmentFinder attachmentFinder;
    
    @Override
    public void execute(Context context) {
        long startTime = System.currentTimeMillis();
        TaskExcelExportData data = (TaskExcelExportData) context.getData();
        ApplicationEventObject event = null;
        try {
            execute(data);
            event = new TaskExcelExportSucceedEventObject(data);
        }
        catch (Exception e) {
            logger.error("导出失败。", e);
            event = new TaskExcelExportFailedEventObject(data);
        }
        
        long endTime = System.currentTimeMillis();
        if (logger.isDebugEnabled()) {
            logger.debug("导出花费时间(ms):" + (endTime - startTime));
        }
        
        // 发送通知
        ApplicationEventBus.getInstance().publishEvent(event);
    }
    
    private void execute(TaskExcelExportData data) throws Exception {
        if (data == null || data.getQueryParameter() == null
            || StringUtils.isBlank(data.getUserId())
            || StringUtils.isBlank(data.getExcelPath())
            || StringUtils.isBlank(data.getExcelUri())
            || StringUtils.isBlank(data.getAttachmentRoot())) {
            throw new BizException("导出参数为空!");
        }
        
        String folderStr = IoUtil.getFolder(data.getExcelPath());
        File folder = new File(folderStr);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        
        List<Map> tasks = taskFinder.getTaskList(data.getQueryParameter(),
                                                 0,
                                                 Integer.MAX_VALUE);
        Workbook workbook = createWorkbook(tasks, data.getAttachmentRoot());
        File excelFile = new File(data.getExcelPath());
        FileOutputStream os = new FileOutputStream(excelFile);
        workbook.write(os);
        IoUtil.close(os);
        
        try {
            excelFile.deleteOnExit();
        }
        catch (Exception e) {
            logger.error("Delete failed:" + data.getExcelPath(), e);
        }
    }
    
    private Workbook createWorkbook(List<Map> tasks, String attachmentRoot) {
        Workbook wb = new SXSSFWorkbook(100);
        Sheet sheet = wb.createSheet("任务导出");
//        sheet.setColumnWidth(17, 30 * 256);
//        sheet.setColumnWidth(19, 30 * 256);
//        sheet.setColumnWidth(21, 30 * 256);
//        sheet.setColumnWidth(23, 30 * 256);
//        sheet.setColumnWidth(25, 30 * 256);
//        sheet.setColumnWidth(27, 30 * 256);
//        sheet.setColumnWidth(29, 30 * 256);
//        sheet.setColumnWidth(31, 30 * 256);
        createExcelHeader(sheet);
        Row row = null;
        for (int i = 1; i <= tasks.size(); i++) {
            Map task = tasks.get(i - 1);
            row = sheet.createRow(i);
            //row.setHeight((short) (15.625 * 100));
            row.createCell(0).setCellValue((String) task.get("name"));
            row.createCell(1).setCellValue((String) task.get("projectName"));
            Date locateDate = (Date) task.get("locateDate");
            if (locateDate != null) {
                row.createCell(2)
                   .setCellValue(DateUtils.getDateStr(locateDate,
                                                      "yyyy-MM-dd HH:mm"));
            }
            else {
                row.createCell(2);
            }
            row.createCell(3)
               .setCellValue((String) task.get("locationAddress"));
            row.createCell(4).setCellValue((String) task.get("execPersonName"));
            row.createCell(5).setCellValue((String) task.get("execOrganName"));
            row.createCell(6).setCellValue((String) task.get("description"));
            row.createCell(7).setCellValue((String) task.get("creatorName"));
            Date assignedDate = (Date) task.get("assignedDate");
            if (assignedDate != null) {
                row.createCell(8)
                   .setCellValue(DateUtils.getDateStr(assignedDate,
                                                      "yyyy-MM-dd HH:mm"));
            }
            else {
                row.createCell(8);
            }
            Date planEndDate = (Date) task.get("planEndDate");
            if (planEndDate != null) {
                row.createCell(9)
                   .setCellValue(DateUtils.getDateStr(planEndDate));
            }
            else {
                row.createCell(9);
            }
            row.createCell(10)
               .setCellValue(NumberUtils.formatDoubleTo6(task.get("longitude")));
            row.createCell(11)
               .setCellValue(NumberUtils.formatDoubleTo6(task.get("latitude")));
            row.createCell(12)
               .setCellValue((String) task.get("locationProvice"));
            row.createCell(13).setCellValue((String) task.get("locationCity"));
            row.createCell(14)
               .setCellValue((String) task.get("locationCounty"));
            row.createCell(15)
               .setCellValue((String) task.get("locationStreet"));
            row.createCell(16)
               .setCellValue((String) task.get("locationNumber"));
            
            // String taskId = (String) task.get("id");
            // List<Attachment> attachments =
            // attachmentFinder.getPhotos(taskId);
            // for (int j = 0; j < attachments.size(); j++) {
            // if (j >= MAX_WORD_IMAGE) {
            // break;
            // }
            // Attachment attachment = attachments.get(j);
            // insertImage(attachment, row, 17 + j * 2, attachmentRoot);
            // row.createCell(18 + j * 2)
            // .setCellValue(attachment.getDescription());
            // }
        }
        
        return wb;
    }
    
    private void insertImage(Attachment attachment,
                             Row row,
                             int col,
                             String attachmentRoot) {
        row.createCell(col);
        
        String realPath = attachmentRoot + "/" + attachment.getOrgiUri();
        File photo = new File(realPath);
        if (!photo.exists()) {
            return;
        }
        
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            BufferedImage bufferImg = ImageIO.read(photo);
            ImageIO.write(bufferImg, "jpg", baos);
            
            Drawing drawing = row.getSheet().createDrawingPatriarch();
            int rowNum = row.getRowNum();
            XSSFClientAnchor anchor = new XSSFClientAnchor(col,
                                                           rowNum,
                                                           col + 1,
                                                           rowNum + 1,
                                                           col,
                                                           rowNum,
                                                           col + 1,
                                                           rowNum + 1);
            drawing.createPicture(anchor,
                                  row.getSheet()
                                     .getWorkbook()
                                     .addPicture(baos.toByteArray(),
                                                 Workbook.PICTURE_TYPE_JPEG));
        }
        catch (Exception e) {
            logger.error(e, e);
        }
        finally {
            if (baos != null) {
                try {
                    baos.close();
                }
                catch (Exception e) {
                    logger.error(e, e);
                }
            }
        }
        
    }
    
    private void createExcelHeader(Sheet sheet) {
        String[] headerNames = new String[] { "任务名称",
                                             "项目",
                                             "定位时间",
                                             "勘察地点",
                                             "勘察人员",
                                             "所在部门",
                                             "勘察内容",
                                             "派发人",
                                             "派发时间",
                                             "要求时间",
                                             "经度",
                                             "纬度",
                                             "省份",
                                             "市州",
                                             "区县",
                                             "街道",
                                             "门牌号"
        // ,
        // "照片1",
        // "描述1",
        // "照片2",
        // "描述2",
        // "照片3",
        // "描述3",
        // "照片4",
        // "描述4",
        // "照片5",
        // "描述5",
        // "照片6",
        // "描述6",
        // "照片7",
        // "描述7",
        // "照片8",
        // "描述8"
                                             };
        Row row = sheet.createRow(0);
        for (int i = 0; i < headerNames.length; i++) {
            row.createCell(i).setCellValue(headerNames[i]);
        }
    }
    
}
